package com.ruoyi.manage.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;
import java.util.Calendar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.manage.mapper.CrInterviewSlotMapper;
import com.ruoyi.manage.mapper.CrInterviewAppointmentMapper;
import com.ruoyi.manage.domain.CrInterviewSlot;
import com.ruoyi.manage.domain.CrInterviewAppointment;
import com.ruoyi.manage.service.ICrInterviewSlotService;

/**
 * 面试时段Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-09-24
 */
@Service
public class CrInterviewSlotServiceImpl implements ICrInterviewSlotService 
{
    @Autowired
    private CrInterviewSlotMapper crInterviewSlotMapper;

    @Autowired
    private CrInterviewAppointmentMapper crInterviewAppointmentMapper;

    /**
     * 查询面试时段
     * 
     * @param slotId 面试时段主键
     * @return 面试时段
     */
    @Override
    public CrInterviewSlot selectCrInterviewSlotBySlotId(Long slotId)
    {
        return crInterviewSlotMapper.selectCrInterviewSlotBySlotId(slotId);
    }

    /**
     * 查询面试时段列表
     * 
     * @param crInterviewSlot 面试时段
     * @return 面试时段
     */
    @Override
    public List<CrInterviewSlot> selectCrInterviewSlotList(CrInterviewSlot crInterviewSlot)
    {
        return crInterviewSlotMapper.selectCrInterviewSlotList(crInterviewSlot);
    }

    /**
     * 新增面试时段
     * 
     * @param crInterviewSlot 面试时段
     * @return 结果
     */
    @Override
    @Transactional
    public int insertCrInterviewSlot(CrInterviewSlot crInterviewSlot)
    {
        crInterviewSlot.setCreateTime(DateUtils.getNowDate());
        return crInterviewSlotMapper.insertCrInterviewSlot(crInterviewSlot);
    }

    /**
     * 修改面试时段
     * 
     * @param crInterviewSlot 面试时段
     * @return 结果
     */
    @Override
    @Transactional
    public int updateCrInterviewSlot(CrInterviewSlot crInterviewSlot)
    {
        crInterviewSlot.setUpdateTime(DateUtils.getNowDate());
        return crInterviewSlotMapper.updateCrInterviewSlot(crInterviewSlot);
    }

    /**
     * 批量删除面试时段
     * 
     * @param slotIds 需要删除的面试时段主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteCrInterviewSlotBySlotIds(Long[] slotIds)
    {
        return crInterviewSlotMapper.deleteCrInterviewSlotBySlotIds(slotIds);
    }

    /**
     * 删除面试时段信息
     * 
     * @param slotId 面试时段主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteCrInterviewSlotBySlotId(Long slotId)
    {
        return crInterviewSlotMapper.deleteCrInterviewSlotBySlotId(slotId);
    }

    /**
     * 根据社团ID查询面试时段列表
     * 
     * @param clubId 社团ID
     * @return 面试时段列表
     */
    @Override
    public List<CrInterviewSlot> selectSlotsByClubId(Long clubId)
    {
        return crInterviewSlotMapper.selectInterviewSlotsByClubId(clubId);
    }

    /**
     * 根据招聘ID查询面试时段列表
     * 
     * @param recruitmentId 招聘ID
     * @return 面试时段列表
     */
    @Override
    public List<CrInterviewSlot> selectSlotsByRecruitmentId(Long recruitmentId)
    {
        return crInterviewSlotMapper.selectInterviewSlotsByRecruitmentId(recruitmentId);
    }

    /**
     * 查询可用的面试时段
     * 
     * @param recruitmentId 招聘ID
     * @param date 日期
     * @return 可用时段列表
     */
    @Override
    public List<CrInterviewSlot> selectAvailableSlots(Long recruitmentId, Date date)
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH, 1);
        Date endDate = cal.getTime();

        // Query available slots for the specific date range
        return crInterviewSlotMapper.selectInterviewSlotsByDateRange(date, endDate, null);
    }

    /**
     * 创建面试时段
     * 
     * @param clubId 社团ID
     * @param recruitmentId 招聘ID（可选）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param location 面试地点
     * @param maxCapacity 最大容量
     * @param description 描述
     * @return 结果
     */
    @Override
    @Transactional
    public int createInterviewSlot(Long clubId, Long recruitmentId, Date startTime, Date endTime, 
                                   String location, Integer maxCapacity, String description)
    {
        // 验证必填字段
        if (clubId == null) {
            throw new RuntimeException("社团ID不能为空");
        }
        if (startTime == null || endTime == null) {
            throw new RuntimeException("面试时间不能为空");
        }
        if (endTime.before(startTime)) {
            throw new RuntimeException("结束时间不能早于开始时间");
        }
        if (startTime.before(new Date())) {
            throw new RuntimeException("面试时间不能早于当前时间");
        }

        // 检查时间冲突
        if (checkTimeConflict(clubId, startTime, endTime, null)) {
            throw new RuntimeException("该时间段与已有面试时段冲突");
        }

        CrInterviewSlot slot = new CrInterviewSlot();
        slot.setClubId(clubId);
        slot.setRecruitmentId(recruitmentId);
        slot.setInterviewDate(DateUtils.parseDate(DateUtils.parseDateToStr("yyyy-MM-dd", startTime)));
        slot.setStartTime(DateUtils.parseDateToStr("HH:mm", startTime));
        slot.setEndTime(DateUtils.parseDateToStr("HH:mm", endTime));
        slot.setLocation(location);
        slot.setMaxApplicants(maxCapacity != null ? maxCapacity : 10); // 默认10人
        slot.setBookedCount(0);
        slot.setStatus("0"); // 可用
        slot.setNotes(description);
        slot.setCreateTime(DateUtils.getNowDate());

        return crInterviewSlotMapper.insertCrInterviewSlot(slot);
    }

    /**
     * 批量创建面试时段
     * 
     * @param slots 时段列表
     * @return 成功创建的数量
     */
    @Override
    @Transactional
    public int batchCreateInterviewSlots(List<CrInterviewSlot> slots)
    {
        if (slots == null || slots.isEmpty()) {
            throw new RuntimeException("时段列表不能为空");
        }

        int successCount = 0;
        for (CrInterviewSlot slot : slots) {
            try {
                // 验证每个时段
                if (slot.getClubId() == null || slot.getStartTime() == null || slot.getEndTime() == null) {
                    continue;
                }

                // 构造完整的开始和结束时间用于冲突检查
                Date fullStartTime = combineDateTime(slot.getInterviewDate(), 
                    DateUtils.parseDate(slot.getStartTime(), "HH:mm"));
                Date fullEndTime = combineDateTime(slot.getInterviewDate(), 
                    DateUtils.parseDate(slot.getEndTime(), "HH:mm"));

                // 检查时间冲突
                if (checkTimeConflict(slot.getClubId(), fullStartTime, fullEndTime, null)) {
                    continue;
                }

                slot.setBookedCount(0);
                slot.setStatus("0");
                slot.setCreateTime(DateUtils.getNowDate());

                if (crInterviewSlotMapper.insertCrInterviewSlot(slot) > 0) {
                    successCount++;
                }
            } catch (Exception e) {
                // 继续处理下一个时段
                continue;
            }
        }

        return successCount;
    }

    /**
     * 检查时段冲突
     * 
     * @param clubId 社团ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param excludeSlotId 排除的时段ID（编辑时使用）
     * @return 是否冲突
     */
    @Override
    public boolean checkTimeConflict(Long clubId, Date startTime, Date endTime, Long excludeSlotId)
    {
        // Extract date and time components
        Calendar cal = Calendar.getInstance();
        cal.setTime(startTime);
        Date interviewDate = DateUtils.parseDate(DateUtils.parseDateToStr("yyyy-MM-dd", startTime));
        String startTimeStr = DateUtils.parseDateToStr("HH:mm", startTime);
        String endTimeStr = DateUtils.parseDateToStr("HH:mm", endTime);

        List<CrInterviewSlot> conflictSlots = crInterviewSlotMapper.checkTimeSlotConflict(
            clubId, interviewDate, startTimeStr, endTimeStr, excludeSlotId);

        return !conflictSlots.isEmpty();
    }

    /**
     * 更新时段容量
     * 
     * @param slotId 时段ID
     * @param change 容量变化（+1或-1）
     * @return 结果
     */
    @Override
    @Transactional
    public int updateSlotCapacity(Long slotId, int change)
    {
        CrInterviewSlot slot = crInterviewSlotMapper.selectCrInterviewSlotBySlotId(slotId);
        if (slot == null) {
            throw new RuntimeException("面试时段不存在");
        }

        int newBookedCount = (slot.getBookedCount() != null ? slot.getBookedCount() : 0) + change;
        if (newBookedCount < 0) {
            throw new RuntimeException("预约数量不能为负数");
        }

        return crInterviewSlotMapper.updateBookedCount(slotId, change);
    }

    /**
     * 获取时段的预约数量
     * 
     * @param slotId 时段ID
     * @return 预约数量
     */
    @Override
    public int getSlotBookingCount(Long slotId)
    {
        CrInterviewAppointment queryParam = new CrInterviewAppointment();
        queryParam.setSlotId(slotId);
        queryParam.setStatus("1"); // 已确认的预约

        List<CrInterviewAppointment> appointments = crInterviewAppointmentMapper.selectCrInterviewAppointmentList(queryParam);
        return appointments.size();
    }

    /**
     * 检查时段是否可预约
     * 
     * @param slotId 时段ID
     * @return 是否可预约
     */
    @Override
    public boolean isSlotAvailable(Long slotId)
    {
        CrInterviewSlot slot = crInterviewSlotMapper.selectCrInterviewSlotBySlotId(slotId);
        if (slot == null) {
            return false;
        }

        // 检查状态：修复状态映射 (0=可用, 1=不可用)
        if (!"0".equals(slot.getStatus())) {
            return false;
        }

        // 检查时间是否过期（简化检查）
        if (slot.getInterviewDate().before(DateUtils.parseDate(DateUtils.parseDateToStr("yyyy-MM-dd", new Date())))) {
            return false;
        }

        // 检查容量
        int bookedCount = slot.getBookedCount() != null ? slot.getBookedCount() : 0;
        int maxCapacity = slot.getMaxApplicants() != null ? slot.getMaxApplicants() : 0;

        return bookedCount < maxCapacity;
    }

    /**
     * 关闭面试时段
     * 
     * @param slotId 时段ID
     * @param clubId 社团ID
     * @return 结果
     */
    @Override
    @Transactional
    public int closeInterviewSlot(Long slotId, Long clubId)
    {
        CrInterviewSlot slot = crInterviewSlotMapper.selectCrInterviewSlotBySlotId(slotId);
        if (slot == null) {
            throw new RuntimeException("面试时段不存在");
        }

        if (!slot.getClubId().equals(clubId)) {
            throw new RuntimeException("只能关闭本社团的面试时段");
        }

        slot.setStatus("1"); // 不可用
        slot.setUpdateTime(DateUtils.getNowDate());

        return crInterviewSlotMapper.updateCrInterviewSlot(slot);
    }

    /**
     * 重新开放面试时段
     * 
     * @param slotId 时段ID
     * @param clubId 社团ID
     * @return 结果
     */
    @Override
    @Transactional
    public int reopenInterviewSlot(Long slotId, Long clubId)
    {
        CrInterviewSlot slot = crInterviewSlotMapper.selectCrInterviewSlotBySlotId(slotId);
        if (slot == null) {
            throw new RuntimeException("面试时段不存在");
        }

        if (!slot.getClubId().equals(clubId)) {
            throw new RuntimeException("只能重新开放本社团的面试时段");
        }

        // 检查时间是否已过期（简化检查）
        if (slot.getInterviewDate().before(DateUtils.parseDate(DateUtils.parseDateToStr("yyyy-MM-dd", new Date())))) {
            throw new RuntimeException("面试时间已过，无法重新开放");
        }

        slot.setStatus("0"); // 可用
        slot.setUpdateTime(DateUtils.getNowDate());

        return crInterviewSlotMapper.updateCrInterviewSlot(slot);
    }

    /**
     * 获取社团的面试时段统计
     * 
     * @param clubId 社团ID
     * @return 统计信息
     */
    @Override
    public Map<String, Object> getClubSlotStatistics(Long clubId)
    {
        Map<String, Object> statistics = new HashMap<>();
        
        List<CrInterviewSlot> allSlots = crInterviewSlotMapper.selectInterviewSlotsByClubId(clubId);
        statistics.put("totalSlots", allSlots.size());

        // 按状态统计
        long availableCount = allSlots.stream().filter(slot -> "0".equals(slot.getStatus())).count();
        long unavailableCount = allSlots.stream().filter(slot -> "1".equals(slot.getStatus())).count();

        statistics.put("availableSlots", availableCount);
        statistics.put("unavailableSlots", unavailableCount);

        // 总容量和已预约统计
        int totalCapacity = allSlots.stream().mapToInt(slot -> slot.getMaxApplicants() != null ? slot.getMaxApplicants() : 0).sum();
        int totalBooked = allSlots.stream().mapToInt(slot -> slot.getBookedCount() != null ? slot.getBookedCount() : 0).sum();

        statistics.put("totalCapacity", totalCapacity);
        statistics.put("totalBooked", totalBooked);
        statistics.put("availableCapacity", totalCapacity - totalBooked);

        return statistics;
    }

    /**
     * 获取时段的详细统计
     * 
     * @param slotId 时段ID
     * @return 统计信息
     */
    @Override
    public Map<String, Object> getSlotStatistics(Long slotId)
    {
        Map<String, Object> statistics = new HashMap<>();
        
        CrInterviewSlot slot = crInterviewSlotMapper.selectCrInterviewSlotBySlotId(slotId);
        if (slot == null) {
            return statistics;
        }

        statistics.put("maxCapacity", slot.getMaxApplicants());
        statistics.put("bookedCount", slot.getBookedCount());
        statistics.put("availableCount", (slot.getMaxApplicants() != null ? slot.getMaxApplicants() : 0) - 
                                         (slot.getBookedCount() != null ? slot.getBookedCount() : 0));

        // 获取预约详细信息
        CrInterviewAppointment queryParam = new CrInterviewAppointment();
        queryParam.setSlotId(slotId);
        List<CrInterviewAppointment> appointments = crInterviewAppointmentMapper.selectCrInterviewAppointmentList(queryParam);

        long confirmedCount = appointments.stream().filter(app -> "1".equals(app.getStatus())).count();
        long pendingCount = appointments.stream().filter(app -> "0".equals(app.getStatus())).count();

        statistics.put("confirmedAppointments", confirmedCount);
        statistics.put("pendingAppointments", pendingCount);

        return statistics;
    }

    /**
     * 查询即将开始的面试时段
     * 
     * @param hours 小时数（几小时内开始）
     * @return 时段列表
     */
    @Override
    public List<CrInterviewSlot> getUpcomingSlots(int hours)
    {
        Calendar cal = Calendar.getInstance();
        Date startDate = cal.getTime();
        cal.add(Calendar.HOUR_OF_DAY, hours);
        Date endDate = cal.getTime();

        return crInterviewSlotMapper.selectInterviewSlotsByDateRange(startDate, endDate, null);
    }

    /**
     * 查询已过期的面试时段
     * 
     * @return 时段列表
     */
    @Override
    public List<CrInterviewSlot> getExpiredSlots()
    {
        CrInterviewSlot queryParam = new CrInterviewSlot();
        queryParam.setStatus("0"); // 仍为可用状态但时间已过
        
        List<CrInterviewSlot> allSlots = crInterviewSlotMapper.selectCrInterviewSlotList(queryParam);
        
        return allSlots.stream()
                .filter(slot -> slot.getInterviewDate().before(new Date()))
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 自动更新过期时段状态
     * 
     * @return 更新数量
     */
    @Override
    @Transactional
    public int updateExpiredSlotsStatus()
    {
        List<CrInterviewSlot> expiredSlots = getExpiredSlots();
        
        if (expiredSlots.isEmpty()) {
            return 0;
        }

        Long[] slotIds = expiredSlots.stream()
                .map(CrInterviewSlot::getSlotId)
                .toArray(Long[]::new);

        return crInterviewSlotMapper.batchUpdateSlotStatus(slotIds, "2"); // 已过期
    }

    /**
     * 复制面试时段（用于批量创建相似时段）
     * 
     * @param sourceSlotId 源时段ID
     * @param targetDates 目标日期列表
     * @return 结果
     */
    @Override
    @Transactional
    public int copyInterviewSlot(Long sourceSlotId, List<Date> targetDates)
    {
        CrInterviewSlot sourceSlot = crInterviewSlotMapper.selectCrInterviewSlotBySlotId(sourceSlotId);
        if (sourceSlot == null) {
            throw new RuntimeException("源面试时段不存在");
        }

        if (targetDates == null || targetDates.isEmpty()) {
            throw new RuntimeException("目标日期列表不能为空");
        }

        int successCount = 0;
        for (Date targetDate : targetDates) {
            try {
                // 计算新的开始和结束时间
                Date newStartTime = combineDateTime(targetDate, 
                    DateUtils.parseDate(sourceSlot.getStartTime(), "HH:mm"));
                Date newEndTime = combineDateTime(targetDate, 
                    DateUtils.parseDate(sourceSlot.getEndTime(), "HH:mm"));

                // 检查时间冲突
                if (checkTimeConflict(sourceSlot.getClubId(), newStartTime, newEndTime, null)) {
                    continue;
                }

                CrInterviewSlot newSlot = new CrInterviewSlot();
                newSlot.setClubId(sourceSlot.getClubId());
                newSlot.setRecruitmentId(sourceSlot.getRecruitmentId());
                newSlot.setInterviewDate(targetDate);
                newSlot.setStartTime(sourceSlot.getStartTime());
                newSlot.setEndTime(sourceSlot.getEndTime());
                newSlot.setLocation(sourceSlot.getLocation());
                newSlot.setMaxApplicants(sourceSlot.getMaxApplicants());
                newSlot.setBookedCount(0);
                newSlot.setStatus("0");
                newSlot.setNotes(sourceSlot.getNotes());
                newSlot.setCreateTime(DateUtils.getNowDate());

                if (crInterviewSlotMapper.insertCrInterviewSlot(newSlot) > 0) {
                    successCount++;
                }
            } catch (Exception e) {
                continue;
            }
        }

        return successCount;
    }

    /**
     * 导出面试时段数据
     * 
     * @param crInterviewSlot 查询条件
     * @return 时段列表
     */
    @Override
    public List<CrInterviewSlot> exportInterviewSlots(CrInterviewSlot crInterviewSlot)
    {
        return crInterviewSlotMapper.selectCrInterviewSlotList(crInterviewSlot);
    }

    /**
     * 辅助方法：合并日期和时间
     */
    private Date combineDateTime(Date date, Date time) {
        Calendar dateCal = Calendar.getInstance();
        dateCal.setTime(date);
        
        Calendar timeCal = Calendar.getInstance();
        timeCal.setTime(time);
        
        dateCal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY));
        dateCal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE));
        dateCal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND));
        
        return dateCal.getTime();
    }
}